package com.wzcl.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.wzcl.app.dao.model.Grade;
import com.wzcl.app.dao.repository.GradeRepository;
import com.wzcl.app.model.common.BusinessException;
import com.wzcl.app.model.common.CodeMsg;
import com.wzcl.app.model.dto.GradeDto;
import com.wzcl.app.service.GradeService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

@Log4j2
@Service
public class GradeServiceImpl implements GradeService {

    @Autowired
    private GradeRepository gradeRepository;


    @Override
    @CacheEvict(value = "Grade", allEntries = true)
    public Grade addGrade(GradeDto gradeDto) {
        Grade grade = new Grade();
        BeanUtils.copyProperties(gradeDto, grade, "id");
        return gradeRepository.save(grade);
    }

    @Override
    @CacheEvict(value = "Grade", allEntries = true)
    public Grade delGradeById(Integer id) {
        //校验获取
        Grade grade = getAndCheckById(id);
        //删除
        log.info("Grade:{} Physical deletion", JSON.toJSONString(grade));
        gradeRepository.delete(grade);
        return grade;
    }

    @Override
    @CacheEvict(value = "Grade", allEntries = true)
    public Grade updateGrade(GradeDto gradeDto) {
        //校验获取
        Grade grade = getAndCheckById(gradeDto);
        //修改
        BeanUtils.copyProperties(gradeDto, grade, "id");
        return gradeRepository.save(grade);
    }

    @Override
    @Cacheable(value = "Grade", keyGenerator = "cacheKeyGenerator")
    public Grade getGradeById(Integer id) {
        return gradeRepository.findById(id).orElse(null);
    }

    @Override
    @Cacheable(value = "Grade", keyGenerator = "cacheKeyGenerator")
    public Grade getAndCheckById(Integer id) {
        if (id == null) {
            throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL, "缺少年级id");
        }
        Grade grade = getGradeById(id);
        if (grade == null) {
            throw new BusinessException(CodeMsg.GRADE_NOT_EXIST);
        }
        return grade;
    }

    @Override
    @Cacheable(value = "Grade", keyGenerator = "cacheKeyGenerator")
    public List<Grade> getGradeList(GradeDto gradeDto) {
        return gradeRepository.findAll(getSpecification(gradeDto), gradeDto.getSort());
    }

    private Specification<Grade> getSpecification(GradeDto gradeDto) {
        return new Specification<Grade>() {
            @Override
            public Predicate toPredicate(Root<Grade> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<Predicate>();
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
    }
}
